#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <semaphore.h>
#include "ringfifo.h"


#define RINGFIFO_MUTEX 1
sem_t *mutex, *empty, *full;

void create_ringfifo(CircularBuffer* cb) {
    int fd;
    // 创建共享内存
    fd = shm_open(SHARED_MEM_NAME, O_CREAT | O_RDWR, 0666);
    if (fd == -1) {
        perror("[ringfifo]shm_open");
        exit(EXIT_FAILURE);
    }
    ftruncate(fd, BUFFER_SIZE);
    void * share_mem = mmap(NULL, BUFFER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    cb->in  = (int *)share_mem;
    cb->out = (int *)share_mem +1;
    cb->buffer = (char *)share_mem +8;
    memset(share_mem,0,BUFFER_SIZE);
    if (cb == MAP_FAILED) {
        perror("[ringfifo]mmap");
        exit(EXIT_FAILURE);
    }
    // 创建信号量
    mutex = sem_open(SEM_MUTEX_NAME, O_CREAT, 0666, 1);
    empty = sem_open(SEM_EMPTY_NAME, O_CREAT, 0666, BUFFER_SIZE);
    full = sem_open(SEM_FULL_NAME, O_CREAT, 0666, 0);

    int value;
    sem_getvalue(mutex, &value);
    sem_getvalue(empty, &value);
    sem_getvalue(full, &value);

    if (mutex == SEM_FAILED || empty == SEM_FAILED || full == SEM_FAILED) {
        perror("[ringfifo]sem_open");
        exit(EXIT_FAILURE);
    }
}

void get_ringfifo(CircularBuffer* cb)
{
    int fd;
    // 创建共享内存
    fd = shm_open(SHARED_MEM_NAME, O_RDWR, 0666);
    if (fd == -1) {
        perror("[ringfifo]shm_open");
        exit(EXIT_FAILURE);
    }
    void * share_mem = mmap(NULL, BUFFER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    cb->in  = (int *)share_mem;
    cb->out = (int *)share_mem +1;
    cb->buffer = (char *)share_mem +8;
    for(int i = 0;i < 32;i++)
        printf("%x ",cb->buffer[i]);
    printf("\n");
    mutex = sem_open(SEM_MUTEX_NAME, 0);
    empty = sem_open(SEM_EMPTY_NAME, 0);
    full = sem_open(SEM_FULL_NAME, 0);
    int value;
    sem_getvalue(mutex, &value);
    sem_getvalue(empty, &value);
    sem_getvalue(full, &value);
    if (mutex == SEM_FAILED || empty == SEM_FAILED || full == SEM_FAILED) {
        perror("[ringfifo]sem_open");
        exit(EXIT_FAILURE);
    }
}

void destroy_ringfifo(CircularBuffer* cb) {
        // 关闭并删除共享内存和信号量
    munmap(cb->buffer, BUFFER_SIZE);
    shm_unlink(SHARED_MEM_NAME);
    sem_close(mutex);
    sem_close(empty);
    sem_close(full);
    sem_unlink(SEM_MUTEX_NAME);
    sem_unlink(SEM_EMPTY_NAME);
    sem_unlink(SEM_FULL_NAME);
}

void ringfifo_write(CircularBuffer* cb, const char* data,int length) {
#if RINGFIFO_MUTEX
    sem_wait(empty);
    sem_wait(mutex);
#endif
      // 写入数据
    for (int i = 0; i < length; i++) {
        cb->buffer[*(cb->in)] = data[i];
        *(cb->in) = (*(cb->in) + 1) % BUFFER_SIZE;
    }
    //cb->frameLength[*(cb->in)] = length;
    printf("=====================>[%d][%d]\n",*cb->in,*cb->out);
    // 更新写入位置
    #if RINGFIFO_MUTEX
    sem_post(mutex);
    sem_post(full);
    #endif

}

int ringfifo_read(CircularBuffer* cb, char* data, int length) {
    #if RINGFIFO_MUTEX
    int ret = 0;
    sem_wait(full);
    sem_wait(mutex);
    #endif
    if (*(cb->out) == *(cb->in)) {
#if RINGFIFO_MUTEX
        sem_post(mutex);
        sem_post(empty);
#endif
        return 0; // 返回读取的有效数据长度为 0
    }
    // 计算实际可读取的数据长度
    int availableLength;
    if (*(cb->in) > *(cb->out)) {
        availableLength = *(cb->in) - *(cb->out);
    } else {
        availableLength = BUFFER_SIZE - (*(cb->out) - *(cb->in));
    }
    if (availableLength > length) {
        availableLength = length;
    }

    // 读取数据
    for (int i = 0; i < availableLength; i++) {
        data[i] = cb->buffer[*(cb->out)];
        // 更新读取位置
        *(cb->out) = (*(cb->out) + 1) % BUFFER_SIZE;
    }

    
#if RINGFIFO_MUTEX
    sem_post(mutex);
    sem_post(empty);
#endif
    return  availableLength;
}
